﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.ComponentModel;
using System.IO;
using System.Collections.ObjectModel;
using System.Windows;
using System.Threading;

namespace BDSim
{
    /// <summary>
    /// 接收机
    /// </summary>
    [TypeConverter(typeof(PropertySorter))]
    public class CReceiver : BDSimObject, IPPositionEvaluation
    {
        public CReceiver()
        {
            DataProvider.Parent = this;
            DataProvider.DefineCommand();
            Menu.ItemsSource = _DataProvider.MenuCommandList;
        }

        #region //所属用户
        UserBaseModel _Parent;

        [XmlIgnore, Browsable(false)]
        public UserBaseModel Parent
        {
            get { return _Parent; }
            set { _Parent = value; }
        }
        #endregion

        #region 字段

        #region 界面设置信息
        //private string _Name;//接收机名称，界面显示
        private ERecType _RecType = ERecType.BD;//接收机类型，界面设置
        //private RecPosXYZClass _DeltaPos = new RecPosXYZClass() { X = 0.0, Y = 0.0, Z = 0.0 };//安装位置，界面设置
        private double _DeltaPos_X = 0.0;//安装位置X
        private double _DeltaPos_Y = 0.0;//安装位置Y
        private double _DeltaPos_Z = 0.0;//安装位置Z
        private PosENUClass _U_Off = new PosENUClass();//接收机在东北天的相位中心偏差（PCO）

        private RecInstallMatrix _RecInstallM;//安装矩阵，界面设置
        private double _Elelim = 5;//观测截止仰角，单位：度；界面设置
        private List<EFrePoint> _RecFre = new List<EFrePoint>() { { EFrePoint.BD_B1 }, { EFrePoint.BD_B2 }, { EFrePoint.BD_B3 } };//接收机的频点选择，界面设置

        private bool _IsGenObsData = true;
        private bool _IsPosition = true;
        private EPositionType _PositionType = EPositionType.最小二乘法;

        //观测误差控制及误差模型选择
        private ObsErrFlagClass _ObsErrCtrlFlag = new ObsErrFlagClass();//观测数据生成控制开关，界面设置
        private double _PseudoRanThH = 0.3;//不超过分米量级，界面设置
        private double _CarrRanThH = 0.003;//不超过毫米量级，界面设置

        private EIonModelTypeObs _IonModelObs = EIonModelTypeObs.十五阶球谐模型;//观测数据仿真的电离层模型，界面设置
        private ERelModelType _RelModelObs;//观测数据仿真使用的相对论效应模型，界面设置
        private ESatClkModelType _SatclkModelObs;//观测数据仿真使用的卫星钟模型，界面设置
        private ETroModelType _TroModelObs;//观测数据仿真使用的对流层模型，界面设置

        //定位解算误差控制
        private EIonModelType _IonModelPVT = EIonModelType.DoubleFre;//定位解算使用的电离层模型，界面设置
        private ERelModelType _RelModelPVT;//定位解算使用的相对论效应模型，界面设置
        private ESatClkModelType _SatclkModelPVT;//定位解算使用的卫星钟模型，界面设置
        private ETroModelType _TroModelPVT;//定位解算使用的对流层模型，界面设置
        //private RanSet _RanModel;
        #endregion 界面设置信息

        [XmlIgnore]
        public Dictionary<ERecType, List<EFrePoint>> RecType_Fre = new Dictionary<ERecType, List<EFrePoint>>();//多模接收机多频点
        [XmlIgnore]
        public List<Dictionary<EConstellationType, Dictionary<string, List<ObsReceiverOutput>>>> ALLObsSatsDataDic_ConType;

        /// <summary>
        /// 接收机的位置速度，界面不显示，只能外部导入
        /// </summary>
        private NodePosVel RecPVECF;//接收机的ECF位置

        //系统中所有卫星的信息
        /// <summary>
        /// 存储单个时刻所有卫星的10个点位置速度数据
        /// </summary>
        private List<List<Queue<NodePosVel>>> satsPVQueue;//，仅接收机使用
        //private List<List<int>> satNowNum;//用于记录当前读取的卫星列表的编号标志，仅接收机使用


        //接收机输出
        private List<List<ObsReceiverOutput>> _ObsSatsDataList;//当前时刻可见星的所有频点观测数据，属性不显示
        private List<List<List<ObsReceiverOutput>>> _AllObsSatsDataList;//按照仿真步长实时增加可见星的观测数据，属性不显示

        private Dictionary<string, List<ObsReceiverOutput>> _ObsSatsDataDic;//当前时刻可见星的所有频点观测数据，属性不显示
        private List<Dictionary<string, List<ObsReceiverOutput>>> _AllObsSatsDataDic;//按照仿真步长实时增加可见星的观测数据，属性不显示

        private Dictionary<EConstellationType, Dictionary<string, List<ObsReceiverOutput>>> _ObsSatsDataDic_ConType;//分星座系统存储的当前时刻可见星的所有频点观测数据，属性不显示


       
        [XmlIgnore]
        Dictionary<EConstellationType, List<EFrePoint>> frequencys_ConType;//分星座存储频点

        private NodePosVel _FixedPosVelXYZ;//接收机定位结果

        Dictionary<EConstellationType, PPositionning_Output> RecFixedData;

        /// <summary>
        /// 星空参数列表
        /// </summary>
        List<SatPredictStatus> SatSpaceParamList = new List<SatPredictStatus>();

        /// <summary>
        /// 当前接收机DOP值
        /// </summary>
        DopDLL.DopOutput DopResult;

        //string directotyname;//文件夹名称

        //string filename;//数据文件的名称

        //int[] timeIdPre;//用于判断是否更新卫星数据序列中的取值
        List<List<int>> timeIdPreList;//分星座，用于判断是否更新卫星数据序列中的取值
        int SubGroundSegmentNumFlag = 0;//用于对没有地面站的情况进行提示
        int StaNumFlag = 0;//用于对没有主控站的情况进行提示（有主控站，没列表）
        int MasterStaFlag = 0;//用于对没有主控站个数的情况进行提示
        int EphNumFlag = 0;//用于对没有星历数据的情况进行提示
        int SatNumFlag = 0;//用于对可见卫星数少于4时进行提示

        //int ephemerisIndex = 0;
        //#region 存储数据
        //string directoryname;//观测误差数据文件夹名称，暂时存储过程数据
        //#endregion 存储数据

        #region 更新接收机定位评估结果
        [XmlIgnore, Browsable(false)]
        Action<NodePosVel, NodePosVel, UTCTime, List<SatPredictStatus>, DopDLL.DopOutput> _UpDatePPositionResult;
        #endregion

        #endregion 字段

        #region 属性

        #region 界面设置信息

        #region 基本信息
        /// <summary>
        /// 接收机名称
        /// </summary>
        [XmlAttribute, DescriptionAttribute("接收机名称"), CategoryAttribute("基本信息"), PropertyOrder(2)]
        public string Name
        {
            get { return _Name; }
            set { _Name = value; NotifyPropertyChanged("Name"); }
        }
        /// <summary>
        /// 接收机类型，说明是BD还是GPS接收机
        /// </summary>
        [XmlIgnore, XmlAttribute, Browsable(false), DescriptionAttribute("接收机类型，说明是BD还是GPS接收机"), CategoryAttribute("基本信息"), PropertyOrder(3)]
        public ERecType RecType
        {
            get { return _RecType; }
            set { _RecType = value; }
        }
        /// <summary>
        /// 接收机频点选择
        /// </summary>
        [XmlIgnore, Browsable(false), DescriptionAttribute("接收机频点选择"), CategoryAttribute("基本信息"), PropertyOrder(4)]
        public List<EFrePoint> RecFre
        {
            get { return _RecFre; }
            set { _RecFre = value; }
        }

        /// <summary>
        /// 接收机相对于载体的安装位置
        /// </summary>
        //[DescriptionAttribute("接收机相对于载体的安装位置（载体坐标系，使用右前上）"), CategoryAttribute("基本信息"), PropertyOrder(5)]
        //public PosXYZClass DeltaPos
        //{
        //    get { return _DeltaPos; }
        //    set { _DeltaPos = value; }
        //}
        /// <summary>
        /// 接收机相对于载体的安装位置X
        /// </summary>
        [DescriptionAttribute("接收机相对于载体的安装位置（载体坐标系，使用右前上）"), CategoryAttribute("基本信息"), PropertyOrder(5)]
        public double DeltaPos_X
        {
            get { return _DeltaPos_X; }
            set
            {
                if (Math.Abs(value) > 1)
                {
                    DlgReportPropertyInfo("接收机相对于载体在X方向的偏移量不大于1m!");
                    return;
                }
                _DeltaPos_X = value;
                NotifyPropertyChanged("DeltaPos_X");
            }
        }
        /// <summary>
        /// 接收机相对于载体的安装位置Y
        /// </summary>
        [DescriptionAttribute("接收机相对于载体的安装位置（载体坐标系，使用右前上）"), CategoryAttribute("基本信息"), PropertyOrder(6)]
        public double DeltaPos_Y
        {
            get { return _DeltaPos_Y; }
            set
            {
                if (Math.Abs(value) > 2)
                {
                    DlgReportPropertyInfo("接收机相对于载体在Y方向的偏移量不大于2m!");
                    return;
                }
                _DeltaPos_Y = value;
                NotifyPropertyChanged("DeltaPos_Y");
            }
        }
        /// <summary>
        /// 接收机相对于载体的安装位置Z
        /// </summary>
        [DescriptionAttribute("接收机相对于载体的安装位置（载体坐标系，使用右前上）"), CategoryAttribute("基本信息"), PropertyOrder(7)]
        public double DeltaPos_Z
        {
            get { return _DeltaPos_Z; }
            set
            {
                if (Math.Abs(value) > 1)
                {
                    DlgReportPropertyInfo("接收机相对于载体在z方向的偏移量不大于1m!");
                    return;
                }
                _DeltaPos_Z = value;
                NotifyPropertyChanged("DeltaPos_Z");
            }
        }

        [DescriptionAttribute("接收机相对于东北天的相位中心偏移量"), CategoryAttribute("基本信息"), PropertyOrder(5)]
        public PosENUClass U_Off
        {
            get { return _U_Off; }
            set { _U_Off = value; }
        }

        /// <summary>
        /// 接收机相对于载体的安装矩阵
        /// </summary>
        [XmlIgnore, DescriptionAttribute("接收机相对于载体的安装矩阵"), CategoryAttribute("基本信息"), PropertyOrder(6), Browsable(false)]
        public RecInstallMatrix RecInstallM
        {
            get { return _RecInstallM; }
            set { _RecInstallM = value; }
        }
        #endregion 基本信息

        #region 业务控制
        /// <summary>
        /// 是否生成观测数据
        /// </summary>
        [XmlAttribute, DescriptionAttribute("观测数据仿真开关，true为具备该功能；false为不具备该功能。该功能同时受到场景中的开关控制"), CategoryAttribute("业务控制")]
        public bool IsGenObsData
        {
            get { return _IsGenObsData; }
            set { _IsGenObsData = value; }
        }

        /// <summary>
        /// 是否定位
        /// </summary>
        [XmlAttribute, DescriptionAttribute("定位开关，true为具备该功能；false为不具备该功能。该功能同时受到场景中的开关控制"), CategoryAttribute("业务控制")]
        public bool IsPosition
        {
            get { return _IsPosition; }
            set { _IsPosition = value; }
        }
        #endregion 业务控制

        #region 定位解算设置
        /// <summary>
        /// 定位模式
        /// </summary>
        [XmlAttribute, DescriptionAttribute("定位模式选择，可选最小二乘法、抗差最小二乘法、kalman滤波、抗差kalman滤波、抗差自适应kalman滤波方法，基础版只提供最小二乘法"), CategoryAttribute("定位解算设置"), PropertyOrder(1)]
        public EPositionType PositionType
        {
            get { return _PositionType; }
            set { _PositionType = value; }
        }
        /// <summary>
        /// 定位解算时使用的卫星钟差模型
        /// </summary>
        [XmlAttribute, DescriptionAttribute("定位解算时使用的卫星钟差模型"), CategoryAttribute("定位解算设置"), PropertyOrder(2)]
        public ESatClkModelType SatclkModelPVT
        {
            get { return _SatclkModelPVT; }
            set { _SatclkModelPVT = value; }
        }
        /// <summary>
        /// 定位解算时使用的电离层模型
        /// </summary>
        [XmlAttribute, DescriptionAttribute("定位解算时使用的电离层模型"), CategoryAttribute("定位解算设置"), PropertyOrder(3)]
        public EIonModelType IonModelPVT
        {
            get { return _IonModelPVT; }
            set { _IonModelPVT = value; }
        }

        /// <summary>
        /// 定位解算时使用的对流层模型
        /// </summary>
        [XmlAttribute, DescriptionAttribute("定位解算时使用的对流层模型"), CategoryAttribute("定位解算设置"), PropertyOrder(6)]
        public ETroModelType TroModelPVT
        {
            get { return _TroModelPVT; }
            set { _TroModelPVT = value; }
        }
        /// <summary>
        /// 定位解算时使用的相对论模型
        /// </summary>
        [XmlAttribute, DescriptionAttribute("定位解算时使用的相对论模型"), CategoryAttribute("定位解算设置"), PropertyOrder(7)]
        public ERelModelType RelModelPVT
        {
            get { return _RelModelPVT; }
            set { _RelModelPVT = value; }
        }
        #endregion 定位解算设置

        #region 观测数据仿真设置参数
        /// <summary>
        /// 接收机观测截止仰角
        /// </summary>
        [XmlAttribute, DescriptionAttribute("接收机观测截止仰角"), CategoryAttribute("观测数据仿真设置"), PropertyOrder(1)]
        public double Elelim
        {
            get { return _Elelim; }
            set { _Elelim = value; }
        }

        /// <summary>
        /// 观测数据仿真时使用的卫星钟差模型
        /// </summary>
        [XmlAttribute, DescriptionAttribute("观测数据仿真时使用的卫星钟差模型"), CategoryAttribute("观测数据仿真设置"), PropertyOrder(2)]
        public ESatClkModelType SatclkModelObs
        {
            get { return _SatclkModelObs; }
            set { _SatclkModelObs = value; }
        }
        /// <summary>
        /// 观测数据仿真时使用的电离层模型
        /// </summary>
        [XmlAttribute, DescriptionAttribute("观测数据仿真时使用的电离层模型"), CategoryAttribute("观测数据仿真设置"), PropertyOrder(3)]
        public EIonModelTypeObs IonModelObs
        {
            get { return _IonModelObs; }
            set { _IonModelObs = value; }
        }
        /// <summary>
        ///观测数据仿真时使用的多路径模型
        /// </summary>
        //[XmlAttribute, DescriptionAttribute("观测数据仿真时使用的多路径模型"), CategoryAttribute("观测数据仿真设置"), PropertyOrder(4)]
        //public EMulModelType MulModelObs
        //{
        //    get { return _MulModelObs; }
        //    set { _MulModelObs = value; }
        //}

        /// <summary>
        /// 观测数据仿真时使用的相位中心偏移模型
        /// </summary>
        //[XmlAttribute, DescriptionAttribute("观测数据仿真时使用的相位中心偏移模型"), CategoryAttribute("观测数据仿真设置"), PropertyOrder(5),]
        //public EOffModelType OffModelObs
        //{
        //    get { return _OffModelObs; }
        //    set { _OffModelObs = value; }
        //}

        /// <summary>
        /// 观测数据仿真时使用的对流层模型
        /// </summary>
        [XmlAttribute, DescriptionAttribute("观测数据仿真时使用的对流层模型"), CategoryAttribute("观测数据仿真设置"), PropertyOrder(6)]
        public ETroModelType TroModelObs
        {
            get { return _TroModelObs; }
            set { _TroModelObs = value; }
        }
        /// <summary>
        /// 观测数据仿真时使用的相对论模型
        /// </summary>
        [XmlAttribute, DescriptionAttribute("观测数据仿真时使用的相对论模型"), CategoryAttribute("观测数据仿真设置"), PropertyOrder(7)]
        public ERelModelType RelModelObs
        {
            get { return _RelModelObs; }
            set { _RelModelObs = value; }
        }
        /// <summary>
        /// 观测数据仿真时使用的接收机钟差模型
        /// </summary>
        //[XmlAttribute, DescriptionAttribute("观测数据仿真时使用的接收机钟差模型"), CategoryAttribute("观测数据仿真设置"), PropertyOrder(2)]
        //public ESatClkModelType RecclkModelObs
        //{
        //    get { return _RecclkModelObs; }
        //    set { _RecclkModelObs = value; }
        //}


        /// <summary>
        /// 伪距噪声量级，不超过分米量级
        /// </summary>
        [XmlAttribute, DescriptionAttribute("接收机观测数据生成时的伪距噪声量级，不超过分米量级"), CategoryAttribute("观测数据仿真设置"), PropertyOrder(8)]
        public double PseudoRanThH
        {
            get { return _PseudoRanThH; }
            set { _PseudoRanThH = value; }
        }
        /// <summary>
        /// 载波相位噪声量级，不超过毫米量级
        /// </summary>
        [XmlAttribute, DescriptionAttribute("接收机观测数据生成时的载波相位噪声量级，不超过毫米量级"), CategoryAttribute("观测数据仿真设置"), PropertyOrder(9)]
        public double CarrRanThH
        {
            get { return _CarrRanThH; }
            set { _CarrRanThH = value; }
        }

        /// <summary>
        /// 接收机观测数据生成误差控制开关
        /// </summary>
        //[DescriptionAttribute("接收机观测数据生成误差控制开关"), CategoryAttribute("观测数据仿真设置"), PropertyOrder(10)]
        //public ObsErrFlagClass ObsErrCtrlFlag
        //{
        //    get { return _ObsErrCtrlFlag; }
        //    set { _ObsErrCtrlFlag = value; }
        //}
        
        #endregion 观测数据仿真设置参数


        #endregion 界面设置信息

        #region 生成的观测数据
        /// <summary>
        /// 当前时刻所有可见星的观测数据列表
        /// </summary>
        [XmlIgnore, Browsable(false)]
        public List<List<ObsReceiverOutput>> ObsSatsDataList
        {
            get { return _ObsSatsDataList; }
            set { _ObsSatsDataList = value; }
        }

        /// <summary>
        /// 按照仿真步长实时增加可见星的观测数据，属性不显示
        /// </summary>
        [XmlIgnore, Browsable(false)]
        public List<List<List<ObsReceiverOutput>>> AllObsSatsDataList
        {
            get { return _AllObsSatsDataList; }
            set { _AllObsSatsDataList = value; }
        }

        /// <summary>
        /// 当前时刻可见星的所有频点观测数据，属性不显示，string为卫星名称， List<ObsReceiverOutput>为单颗卫星的所有频点的观测数据，
        /// </summary>
        [XmlIgnore, Browsable(false)]
        public Dictionary<string, List<ObsReceiverOutput>> ObsSatsDataDic
        {
            get { return _ObsSatsDataDic; }
            set { _ObsSatsDataDic = value; }
        }
        /// <summary>
        /// 按照仿真步长实时增加可见星的观测数据，属性不显示
        /// </summary>
        [XmlIgnore, Browsable(false)]
        public List<Dictionary<string, List<ObsReceiverOutput>>> AllObsSatsDataDic
        {
            get { return _AllObsSatsDataDic; }
            set { _AllObsSatsDataDic = value; }
        }
        /// <summary>
        /// 分星座系统存储的当前时刻的观测数据
        /// </summary>
        [XmlIgnore, Browsable(false)]
        public Dictionary<EConstellationType, Dictionary<string, List<ObsReceiverOutput>>> ObsSatsDataDic_ConType
        {
            get { return _ObsSatsDataDic_ConType; }
            set { _ObsSatsDataDic_ConType = value; }
        }
        /// <summary>
        /// 当前时刻的定位结果
        /// </summary>
        [XmlIgnore, Browsable(false)]
        public NodePosVel FixedPosVelXYZ
        {
            get { return _FixedPosVelXYZ; }
            set { _FixedPosVelXYZ = value; }
        }
        #endregion 生成的观测数据

        #region 接收机数据交互模型
        ReceiverDataProvider _DataProvider = new ReceiverDataProvider();
        [XmlIgnore, Browsable(false)]
        public ReceiverDataProvider DataProvider
        {
            get { return _DataProvider; }
            set { _DataProvider = value; }
        }
        #endregion

        #endregion 属性

        #region 包含功能模块
        [XmlIgnore]
        public ObsDataGenModel RecObsDataGen;//接收机对所有可见星的观测数据计算模块
        #endregion 包含功能模块

        #region 初始化
        public override void Init()
        {
            #region 定义参数及模块初始化
            satsPVQueue = new List<List<Queue<NodePosVel>>>();
            //satNowNum = new List<List<int>>();
            _ObsSatsDataList = new List<List<ObsReceiverOutput>>();
            _AllObsSatsDataList = new List<List<List<ObsReceiverOutput>>>();
            _ObsSatsDataDic = new Dictionary<string, List<ObsReceiverOutput>>();
            _AllObsSatsDataDic = new List<Dictionary<string, List<ObsReceiverOutput>>>();
            _ObsSatsDataDic_ConType = new Dictionary<EConstellationType, Dictionary<string, List<ObsReceiverOutput>>>();
            frequencys_ConType = new Dictionary<EConstellationType, List<EFrePoint>>();
            timeIdPreList = new List<List<int>>();
            RecObsDataGen = new ObsDataGenModel();

            SubGroundSegmentNumFlag = 0;//用于对没有地面站的情况进行提示
            StaNumFlag = 0;//用于对没有主控站的情况进行提示（有主控站，没列表）
            MasterStaFlag = 0;//用于对没有主控站个数的情况进行提示
            EphNumFlag = 0;//用于对没有星历数据的情况进行提示
            SatNumFlag = 0;//用于对可见卫星数少于4时进行提示

            #endregion 定义参数及模块初始化

            //接收机位置计算初始化
            RecPosInit();

            //接收机钟差仿真初始化

            //接收机观测数据仿真初始化
            if (IsGenObsData)//判断是否生成观测数据
            {
                ObsDataGenInit();
                //PreviousObsDataGenSim();
            }
            //初始化完成反馈任务执行量
            DlgAddCompleteMission();
        }

        #endregion

        #region 初始化中的方法
        /// <summary>
        /// 根据载体位置、载体姿态、接收机安装位置计算接收机的位置
        /// </summary>
        private void RecPosInit()
        {
            //RecPVECF = Parent.PosVelXYZ;
            double yaw = Parent.UserAttitude.Yaw;
            double pitch = Parent.UserAttitude.Pitch;
            double roll = Parent.UserAttitude.Roll;
            double[] matrix1 = new double[] { Math.Cos(yaw), Math.Sin(yaw), 0, -Math.Sin(yaw), Math.Cos(yaw), 0, 0.0, 0.0, 1 };
            double[] matrix2 = new double[] { 1, 0.0, 0.0, 0.0, Math.Cos(pitch), Math.Sin(pitch), -Math.Sin(pitch), Math.Cos(pitch), 0.0 };
            double[] matrix3 = new double[] { Math.Cos(roll), 0.0, -Math.Sin(roll), 0.0, 1, 0.0, Math.Sin(roll), 0.0, Math.Cos(roll) };
            double[] tempmatrix = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
            double[] B2LMatrix = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };

            CMatrixDLL.MatrixMult(matrix1, matrix2, tempmatrix, 3, 3, 3);
            CMatrixDLL.MatrixMult(tempmatrix, matrix3, B2LMatrix, 3, 3, 3);//求解载体坐标系到东北天坐标系的旋转矩阵

            double[] recpos_B = new double[] { DeltaPos_X, DeltaPos_Y, DeltaPos_Z };
            double[] recpos_L = new double[] { 0.0, 0.0, 0.0 };
            CMatrixDLL.MatrixMult(B2LMatrix, recpos_B, recpos_L, 3, 3, 1);

            ENU_PosVel recenu = new ENU_PosVel();
            recenu.epoch = GlobalCurrentTime;
            recenu.E = recpos_L[0];
            recenu.N = recpos_L[1];
            recenu.U = recpos_L[2];
            recenu.v_E = 0.0;
            recenu.v_N = 0.0;
            recenu.v_U = 0.0;
            TimeSpaceDll.ENU2ECF(Parent.PosVelXYZ, recenu, ECFtype.type_CGCS2000, out RecPVECF);

        }

        /// <summary>
        /// 观测数据生成初始化
        /// </summary>
        private void ObsDataGenInit()
        {

            ALLObsSatsDataDic_ConType = new List<Dictionary<EConstellationType, Dictionary<string, List<ObsReceiverOutput>>>>();
            RecObsDataGen.CurTime = GlobalStartTime;
            RecObsDataGen.RecID = Id;
            RecObsDataGen.RecPV = RecPVECF;//观测数据动态库函数调用时输入用户的使用ECI坐标

            //观测误差控制开关赋值
            //RecObsDataGen.ErrFlag = ObsErrCtrlFlag.ConvertToStruct();

            //IsSatClk;
            switch (SatclkModelObs)
            {
                case ESatClkModelType.多项式模型:
                    RecObsDataGen.IsSatClk = 1;
                    break;
                case ESatClkModelType.不考虑:
                    RecObsDataGen.IsSatClk = 0;
                    break;
                default:
                    break;
            }          
            //IsIion;//
            switch (IonModelObs)
            {
                case EIonModelTypeObs.十五阶球谐模型:
                    RecObsDataGen.IsIion = 1;
                    break;
                case EIonModelTypeObs.全球格网模型:
                    RecObsDataGen.IsIion = 2;
                    break;
                case EIonModelTypeObs.不考虑:
                    RecObsDataGen.IsIion = 0;
                    break;
                default:
                    break;
            }
            //IsItro;//
            switch (TroModelObs)
            {
                case ETroModelType.Hopfield:
                    RecObsDataGen.IsItro = 1;
                    break;
                case ETroModelType.ImprovedHopfield:
                    RecObsDataGen.IsItro = 2;
                    break;
                case ETroModelType.Saastamoinen:
                    RecObsDataGen.IsItro = 3;
                    break;
                case ETroModelType.不考虑:
                    RecObsDataGen.IsItro = 0;
                    break;
                default:
                    break;
            }
            //IsIrel;//
            switch (RelModelObs)
            {
                case ERelModelType.自定义模型:
                    RecObsDataGen.IsIrel = 1;
                    break;
                case ERelModelType.不考虑:
                    RecObsDataGen.IsIrel = 0;
                    break;
                default:
                    break;
            }

            //IsIran;//

            //气象参数赋值（其余参数暂不赋值）
            //RecObsDataGen.MetePara.Pressure = Parent.MeteParamClass.Pressure;
            //RecObsDataGen.MetePara.Temperature = Parent.MeteParamClass.Temperature;
            //RecObsDataGen.MetePara.RelHumidity = Parent.MeteParamClass.RelHumidity;
            RecObsDataGen.MetePara = Parent.MeteParam;

            RecObsDataGen.PosENU = U_Off;//接收机相位中心偏移误差

            //RecObsDataGen.PseudoRanThH = PseudoRanThH;
            //RecObsDataGen.CarrRanThH = CarrRanThH;
            RecObsDataGen.Elelim = Elelim;
            SpaceSegment temp = new SpaceSegment();
            temp = (Parent.Parent.Parent as Scenario).SegmentColletion[0] as SpaceSegment;

            if (temp.ConstellationList.Count() <= 0)
            {
                MessageBox.Show("卫星个数为0，请添加卫星！");
                Thread thd = Thread.CurrentThread;
                BDSimObject.GlobalStatus = ESimStatus.UnInited;
                thd.Abort();
            }

            for (int i = 0; i < temp.ConstellationList.Count(); i++)//根据星座类型进行循环生成观测数据，并根据星座类型分别存储观测数据
            {
                #region 卫星信息赋值
                List<int> satID = new List<int>();
                List<string> satNameList = new List<string>();
                List<List<NodePosVel>> obsSatsPV = new List<List<NodePosVel>>();//所有卫星的位置点
                List<double> obsSatsClk = new List<double>();//所有卫星的钟差

                if (temp.ConstellationList[i].SatelliteCollection.Count() <= 0)
                {
                    string str = string.Format("{0}星座中卫星个数为0，请添加卫星！", temp.ConstellationList[i].ConstellationFeature.ConstellationType.ToString());
                    MessageBox.Show("卫星个数为0，请添加卫星！");
                    Thread thd = Thread.CurrentThread;
                    BDSimObject.GlobalStatus = ESimStatus.UnInited;
                    thd.Abort();
                }

                List<int> timeidpre = new List<int>();
                List<Queue<NodePosVel>> satspvtemp = new List<Queue<NodePosVel>>();
                List<int> satnownumtemp = new List<int>();
                for (int j = 0; j < temp.ConstellationList[i].SatelliteCollection.Count(); j++)//单星座系统内所有卫星位置速度信息提取
                {
                    #region 卫星位置信息赋值
                    Queue<NodePosVel> satPVQueue = new Queue<NodePosVel>();

                    satID.Add(temp.ConstellationList[i].SatelliteCollection[j].Id);//卫星编号赋值
                    satNameList.Add(temp.ConstellationList[i].SatelliteCollection[j].Name);//卫星名称，使用观测数据时需要
                    for (int k = 0; k < 10; k++)
                    {
                        satPVQueue.Enqueue(temp.ConstellationList[i].SatelliteCollection[j].OrbitPVList[k].SatPV_ECI);
                    }

                    satspvtemp.Add(satPVQueue);

                    obsSatsPV.Add(satPVQueue.ToList());//提供给观测数据生成模块
                    satnownumtemp.Add(0);//从卫星列表中提取的起始点的编号

                    timeidpre.Add(0);
                    #endregion 卫星位置信息赋值

                    obsSatsClk.Add(temp.ConstellationList[i].SatelliteCollection[j].Clock.Clk_Err);//卫星钟差赋值

                    RecObsDataGen.SatPhaseOff = new double[3];//卫星相位中心偏移赋值
                    RecObsDataGen.SatPhaseOff = temp.ConstellationList[i].SatelliteCollection[j].PhaseOff;
                }

                satsPVQueue.Add(satspvtemp);//保存，供下次提取卫星轨道数据，分星座存储
                //satNowNum.Add(satnownumtemp);//从卫星列表中提取的起始点的编号，分星座存储
                timeIdPreList.Add(timeidpre);//分系统存储的卫星列表中起始提取点的编号

                RecObsDataGen.SatNum = temp.ConstellationList[i].SatelliteCollection.Count();
                RecObsDataGen.SatsID = satID;
                RecObsDataGen.SatNameList = satNameList;
                RecObsDataGen.SatsPV = obsSatsPV;//观测数据计算模块卫星位置点赋值
                RecObsDataGen.SatsClk = obsSatsClk;//观测数据计算模块卫星钟差赋值
                RecObsDataGen.SatOrbFlag = 1;
                #endregion 卫星信息赋值

                #region 频点赋值
                int FreNum = 0;
                foreach (ERecType recType in RecType_Fre.Keys)
                {
                    if (recType.ToString() == temp.ConstellationList[i].ConstellationFeature.ConstellationType.ToString())
                    {
                        frequencys_ConType.Add(temp.ConstellationList[i].ConstellationFeature.ConstellationType, RecType_Fre[recType]);
                        FreNum += RecType_Fre[recType].Count;
                    }
                }
                if (FreNum == 0)
                {
                    MessageBox.Show("请设置接收机频点！");
                    Thread thd = Thread.CurrentThread;
                    BDSimObject.GlobalStatus = ESimStatus.UnInited;
                    this.Parent.Parent.Parent.Status = ESimStatus.UnInited;
                    thd.Abort();
                }
                if (frequencys_ConType.Keys.Count == 0)
                {
                    MessageBox.Show("接收机频点设置和空间段卫星类型不匹配！");
                    Thread thd = Thread.CurrentThread;
                    BDSimObject.GlobalStatus = ESimStatus.UnInited;
                    this.Parent.Parent.Parent.Status = ESimStatus.UnInited;
                    thd.Abort();
                }

                RecObsDataGen.FreNum = frequencys_ConType[temp.ConstellationList[i].ConstellationFeature.ConstellationType].Count();
                RecObsDataGen.Fres = frequencys_ConType[temp.ConstellationList[i].ConstellationFeature.ConstellationType];
                #endregion 频点赋值

                //随机误差赋值
                CalRan_Input pCalRan_Input;
                RandomNoise Noise = new RandomNoise();
                Thread.Sleep(10);
                Random ran = new Random(unchecked((int)DateTime.Now.Ticks));
                Noise.ran1_iv = new double[32];
                Noise.idum = ran.Next(-10000, 0);
                Noise.RanErr = 0;
                Noise.RWErr = 0.2;
                Noise.PR_idum = 500;
                pCalRan_Input.DeltRanThH = PseudoRanThH;

                pCalRan_Input.pRandomNoise = Noise;
                RecObsDataGen.pCalRan_Input = pCalRan_Input;
                RecObsDataGen.PseudoRanThH = PseudoRanThH;//
                RecObsDataGen.CarrRanThH = CarrRanThH;//
                //------------------------------------------------------------------

                Parent.GetMeteorological(BDSimObject.GlobalCurrentTime);
                RecObsDataGen.MetePara = Parent.MeteParam;

                RecObsDataGen.ObsDataGen();
                ObsSatsDataList = new List<List<ObsReceiverOutput>>();
                ObsSatsDataList = RecObsDataGen.RecObsOutput;
              //  AllObsSatsDataList.Add(ObsSatsDataList);

                ObsSatsDataDic = new Dictionary<string, List<ObsReceiverOutput>>();//
                ObsSatsDataDic = RecObsDataGen.RecObsOutputDic;//
                //if (Scenario._IsTestingMode == false)
                //{
                //    AllObsSatsDataDic.Add(ObsSatsDataDic);
                //}
                // //

                //#region 存储误差数据
                //if (true)
                //{
                //    string defaultpath = Directory.GetCurrentDirectory() + "\\DataRecords\\用户段\\静态用户\\";
                //    DateTime NowTime = DateTime.Now;
                //    string NowTimeString = NowTime.Year.ToString() + string.Format("{0:D2}", NowTime.Month) + string.Format("{0:D2}", NowTime.Day) +
                //        "_" + string.Format("{0:D2}", NowTime.Hour) + "_" + string.Format("{0:D2}", NowTime.Minute) + "_" + string.Format("{0:D2}", NowTime.Second);

                //    directoryname = defaultpath + "自定义数据_" + NowTimeString + "\\";
                //    if (!Directory.Exists(directoryname))
                //    {
                //        Directory.CreateDirectory(directoryname);
                //    }


                //}
                //#endregion 存储误差数据

                ObsSatsDataDic_ConType.Add(temp.ConstellationList[i].ConstellationFeature.ConstellationType, ObsSatsDataDic);

            }
            
        }

     
        #endregion 初始化中的方法

        #region 单步运行
        public override void StepRun()
        {
            RecPosInit();//实时更新接收机的位置、姿态信息
            if (IsGenObsData)//判断是否生成观测数据
            {
                RealTimeObsDataGenSim();
                if (IsPosition)//判断是否进行定位
                {
                    RealTimeRecPVT();
                    if (_UpDatePPositionResult != null)
                    {
                        CalculateSatSpaceParam();
                        NodePosVel ppositionError = new NodePosVel(BDSimObject.GlobalCurrentTime, FixedPosVelXYZ.X - RecPVECF.x, FixedPosVelXYZ.Y - RecPVECF.Y, FixedPosVelXYZ.Z - RecPVECF.Z, FixedPosVelXYZ.VX - Parent.PosVelXYZ.VX, FixedPosVelXYZ.VY - Parent.PosVelXYZ.VY, FixedPosVelXYZ.VZ - Parent.PosVelXYZ.VZ);
                        _UpDatePPositionResult(ppositionError, FixedPosVelXYZ, BDSimObject.GlobalCurrentTime, SatSpaceParamList, DopResult);
                    }
                }

            }


        }
        #endregion 单步运行

        #region 单步运行中的函数
        private void RealTimeObsDataGenSim()
        {
            double nowTime = (BDSimObject.GlobalCurrentTime.Jd - BDSimObject.GlobalStartTime.Jd) * 86400.0;//当前系统运行时刻
           
            RecObsDataGen.CurTime = BDSimObject.GlobalCurrentTime;//更新观测数据计算模型的时间信息
            RecObsDataGen.RecPV = RecPVECF;//跟新观测数据计算模型的接收机位置速度信息

            RecObsDataGen.PosENU = U_Off;//接收机相位中心偏移赋值

            SpaceSegment temp = new SpaceSegment();//获取空间段，使用卫星轨道数据
            temp = (Parent.Parent.Parent as Scenario).SegmentColletion[0] as SpaceSegment;

            ObsSatsDataDic_ConType = new Dictionary<EConstellationType, Dictionary<string, List<ObsReceiverOutput>>>();
            for (int i = 0; i < temp.ConstellationList.Count(); i++)//根据星座类型进行循环生成观测数据，并根据星座类型分别存储观测数据
            {
                #region 卫星信息赋值
                List<int> satID = new List<int>();
                List<string> satNameList = new List<string>();
                List<List<NodePosVel>> obsSatsPV = new List<List<NodePosVel>>();//所有卫星的位置点
                List<double> obsSatsClk = new List<double>();//所有卫星的钟差
                for (int j = 0; j < temp.ConstellationList[i].SatelliteCollection.Count(); j++)//单星座系统内所有卫星位置速度信息提取
                {
                    #region 卫星位置信息赋值
                    satID.Add(temp.ConstellationList[i].SatelliteCollection[j].Id);//卫星编号赋值
                    satNameList.Add(temp.ConstellationList[i].SatelliteCollection[j].Name);//卫星名称，使用观测数据时需要

                    double orbPreStep = temp.ConstellationList[i].SatelliteCollection[j].Orbit.IntegrationParam.StepSize;//获取当前卫星的积分器步长，用于判断使用卫星数据序列中的第几个数据
                    int timeId = (int)(Math.Floor(nowTime + 0.0001) / orbPreStep);//判断从卫星位置信息序列中的取值的标号,即每次取的10个卫星信息序列的中间值的标号
                    //int FlagNum = timeId;//每次取的10个卫星信息序列的中间值的标号
                    List<NodePosVel> satPVList = new List<NodePosVel>();

                    int satPVListNum = temp.ConstellationList[i].SatelliteCollection[j].OrbitPVList.Count();//单系统中单卫星仿真时段内的位置信息个数

                    if (timeId < 5)
                    {
                        timeId = 4;
                    }
                    if (satPVListNum - timeId < 6)
                    {
                        timeId = satPVListNum - 6;
                    }

                    for (int k = 0; k < 10; k++)
                    {
                        satPVList.Add(temp.ConstellationList[i].SatelliteCollection[j].OrbitPVList[timeId - 4 + k].SatPV_ECI);
                    }

                    obsSatsPV.Add(satPVList);

                    #endregion 卫星位置信息赋值

                    obsSatsClk.Add(temp.ConstellationList[i].SatelliteCollection[j].Clock.Clk_Err);//卫星钟差赋值

                    RecObsDataGen.SatPhaseOff = new double[3];//卫星相位中心偏移赋值
                    RecObsDataGen.SatPhaseOff = temp.ConstellationList[i].SatelliteCollection[j].PhaseOff;
                }
                RecObsDataGen.SatNum = temp.ConstellationList[i].SatelliteCollection.Count();
                RecObsDataGen.SatsID = satID;
                RecObsDataGen.SatNameList = satNameList;
                RecObsDataGen.SatsPV = obsSatsPV;//观测数据计算模块卫星位置点赋值
                RecObsDataGen.SatsClk = obsSatsClk;//观测数据计算模块卫星钟差赋值
                RecObsDataGen.SatOrbFlag = 1;
                #endregion 卫星信息赋值

                #region 频点赋值

                RecObsDataGen.FreNum = frequencys_ConType[temp.ConstellationList[i].ConstellationFeature.ConstellationType].Count();
                RecObsDataGen.Fres = frequencys_ConType[temp.ConstellationList[i].ConstellationFeature.ConstellationType];
                #endregion 频点赋值

                Parent.GetMeteorological(BDSimObject.GlobalCurrentTime);
                RecObsDataGen.MetePara = Parent.MeteParam;

                RecObsDataGen.ObsDataGen();
                ObsSatsDataList = new List<List<ObsReceiverOutput>>();
                ObsSatsDataList = RecObsDataGen.RecObsOutput;
              //  AllObsSatsDataList.Add(ObsSatsDataList);

                ObsSatsDataDic = new Dictionary<string, List<ObsReceiverOutput>>();//
                ObsSatsDataDic = RecObsDataGen.RecObsOutputDic;//

                ObsSatsDataDic_ConType.Add(temp.ConstellationList[i].ConstellationFeature.ConstellationType, ObsSatsDataDic);
            }
            if (this.Parent.Parent.Parent.ObsSaveFlag)
            {
                ALLObsSatsDataDic_ConType.Add(ObsSatsDataDic_ConType);
            }
            
        }

        /// <summary>
        /// 实时PVT解算
        /// </summary>
        private void RealTimeRecPVT()
        {
            GroundSegment temp = new GroundSegment();
            temp = (Parent.Parent.Parent as Scenario).SegmentColletion[2] as GroundSegment;

            if ((temp.SubGroundSegmentList.Count <= 0) && (0 == SubGroundSegmentNumFlag))
            {
                MessageBox.Show("没有主控站，不能完成定位！");
                IsPosition = false;
                SubGroundSegmentNumFlag = 1;
            }

            List<EConstellationType> ObsSatsDataDicKey = ObsSatsDataDic_ConType.Keys.ToList();
            RecFixedData = new Dictionary<EConstellationType, PPositionning_Output>();//分星座实时存储的当前时刻的定位结果
            for (int i = 0; i < ObsSatsDataDic_ConType.Count(); i++)//根据观测数据的星座类型进行循环
            {
                foreach (SubGroundSegment subgroundtemp in temp.SubGroundSegmentList)//搜索地面段的类型，判断是否有对应星座类型的星历数据
                {
                    if (subgroundtemp.Type == ObsSatsDataDicKey[i])//地面段类型和星座类型匹配
                    {

                        foreach (StationCollection stacollectiontemp in subgroundtemp.GroundList)//遍历地面段中的站类型，看是否有主控站
                        {
                            if (EStationType.MasterStation == stacollectiontemp.Type)//地面段中有主控站
                            {
                                if ((stacollectiontemp.StationList.Count() <= 0) & (0 == StaNumFlag))
                                {
                                    MessageBox.Show("没有星历数据(请添加主控站或打开星历拟合开关)！");
                                    IsPosition = false;
                                    StaNumFlag = 1;
                                }

                                MasterStaFlag = 1;//标记场景中有主控站，且个数不少于1

                                if (stacollectiontemp.StationList.Count() > 0)
                                {
                                    MasterStation masterstation = (MasterStation)stacollectiontemp.StationList[0];

                                    PPositionning_Input pp_input = new PPositionning_Input();
                                    PPositionning_Param pp_param = new PPositionning_Param();
                                    PPositionning_Output pp_output = new PPositionning_Output();

                                    if ((0 == masterstation.SatEph16Dic.Count()) & (0 == EphNumFlag))
                                    {
                                        MessageBox.Show("没有星历数据，不能完成定位功能！");
                                        EphNumFlag = 1;
                                    }

                                    if (masterstation.SatEph16Dic.Count() > 4)
                                    {
                                        pp_input.CurTime = BDSimObject.GlobalCurrentTime;
                                        pp_input.ReceiverID = Id;
                                        pp_input.ReceiverPos = new double[3] { RecPVECF.x, RecPVECF.y, RecPVECF.z };

                                        pp_input.ObsTotalSatnum = ObsSatsDataDic_ConType[ObsSatsDataDicKey[i]].Count();//获取当前星座中可见星个数
                                        if (pp_input.ObsTotalSatnum > 0)
                                        {
                                            List<string> satNameList = ObsSatsDataDic_ConType[ObsSatsDataDicKey[i]].Keys.ToList();//获取当前星座中可见星名称

                                            double nowTime = (BDSimObject.GlobalCurrentTime.Jd - BDSimObject.GlobalStartTime.Jd) * 86400.0;//运行时间长度
                                            int NavMsgId = (int)(nowTime / 3600.0);//因1小时生成一组星历，用于判断取第几组星历数据
                                            if (NavMsgId == masterstation.SatEph16Dic[satNameList[0]].Count())
                                            {
                                                NavMsgId--;
                                            }

                                            pp_input.ObsSatInfo = new SatInfo[20];
                                            if (pp_input.ObsTotalSatnum >= 4)
                                            {
                                                for (int j = 0; j < pp_input.ObsTotalSatnum; j++)
                                                {
                                                    pp_input.ObsSatInfo[j].SatID = ObsSatsDataDic_ConType[ObsSatsDataDicKey[i]][satNameList[j]][0].SatID;//卫星编号

                                                    //观测数据赋值
                                                    pp_input.ObsSatInfo[j].SatObs.SatID = ObsSatsDataDic_ConType[ObsSatsDataDicKey[i]][satNameList[j]][0].SatID;//卫星编号
                                                    pp_input.ObsSatInfo[j].SatObs.Code_Pseudo = new double[6];
                                                    pp_input.ObsSatInfo[j].SatObs.Carrier_Phase = new double[6];

                                                    for (int k = 0; k < ObsSatsDataDic_ConType[ObsSatsDataDicKey[i]][satNameList[j]].Count(); k++)//有多少个频点的观测数据赋多少个值
                                                    {
                                                        pp_input.ObsSatInfo[j].SatObs.Code_Pseudo[k] = ObsSatsDataDic_ConType[ObsSatsDataDicKey[i]][satNameList[j]][k].SatObs.A_Pseudo_writein;
                                                        pp_input.ObsSatInfo[j].SatObs.Carrier_Phase[k] = ObsSatsDataDic_ConType[ObsSatsDataDicKey[i]][satNameList[j]][k].SatObs.A_Carri_writein;
                                                    }

                                                    //电文数据赋值
                                                    pp_input.ObsSatInfo[j].SingleSatNavMsg.SatID = ObsSatsDataDic_ConType[ObsSatsDataDicKey[i]][satNameList[j]][0].SatID;//卫星编号
                                                    pp_input.ObsSatInfo[j].SingleSatNavMsg.EphemerisSixteen = masterstation.SatEph16Dic[satNameList[j]][NavMsgId];
                                                    pp_input.ObsSatInfo[j].SingleSatNavMsg.ClkErrMsg = masterstation.ClockErrDic[satNameList[j]][NavMsgId];
                                                    pp_input.ObsSatInfo[j].SingleSatNavMsg.IonEightParam= masterstation.IonoFitOutputMsgList[0].IonoFitOutput.EightIonoData;
                                                    //pp_input.ObsSatInfo[j].SingleSatNavMsg.IonEightParam.Alpha1 = 0.7421e-08;
                                                    //pp_input.ObsSatInfo[j].SingleSatNavMsg.IonEightParam.Alpha2 = -0.4149e-07;
                                                    //pp_input.ObsSatInfo[j].SingleSatNavMsg.IonEightParam.Alpha3 = 0.3773e-07;
                                                    //pp_input.ObsSatInfo[j].SingleSatNavMsg.IonEightParam.Beta0 = 0.1249e+06;
                                                    //pp_input.ObsSatInfo[j].SingleSatNavMsg.IonEightParam.Beta1 = 0.6554e+05;
                                                    //pp_input.ObsSatInfo[j].SingleSatNavMsg.IonEightParam.Beta2 = -0.1966e+06;
                                                    //pp_input.ObsSatInfo[j].SingleSatNavMsg.IonEightParam.Beta3 = 0.6554e+05;
                                                }

                                                #region 误差控制参数赋值
                                                pp_param.Iion = 1;
                                                switch (IonModelPVT)
                                                {
                                                    case EIonModelType.EightParam:
                                                        pp_param.m_nMode = 1;
                                                        break;
                                                    case EIonModelType.DoubleFre:
                                                        pp_param.m_nMode = 2;
                                                        break;
                                                    case EIonModelType.不考虑:
                                                        pp_param.Iion = 0;
                                                        break;
                                                    default:
                                                        break;
                                                }

                                                switch (TroModelPVT)//
                                                {
                                                    case ETroModelType.Hopfield:
                                                        pp_param.Itro = 1;
                                                        break;
                                                    case ETroModelType.ImprovedHopfield:
                                                        pp_param.Itro = 1;
                                                        break;
                                                    case ETroModelType.Saastamoinen:
                                                        pp_param.Itro = 1;
                                                        break;
                                                    case ETroModelType.不考虑:
                                                        pp_param.Itro = 0;
                                                        break;
                                                    default:
                                                        break;
                                                }

                                                switch (RelModelPVT)
                                                {
                                                    case ERelModelType.自定义模型:
                                                        pp_param.Irel = 1;
                                                        break;
                                                    case ERelModelType.不考虑:
                                                        pp_param.Irel = 0;
                                                        break;
                                                    default:
                                                        break;
                                                }

                                                switch (SatclkModelPVT)
                                                {
                                                    case ESatClkModelType.多项式模型:
                                                        pp_param.Iclo = 1;
                                                        break;
                                                    case ESatClkModelType.不考虑:
                                                        pp_param.Iclo = 0;
                                                        break;
                                                    default:
                                                        break;
                                                }
                                                #endregion 误差控制参数赋值

                                                #region 频点赋值
                                                pp_param.Freq = new double[3];
                                                for (int k = 0; k < frequencys_ConType[ObsSatsDataDicKey[i]].Count(); k++)//定位时输入的接收机频率不大于3
                                                {
                                                    FreFlagValue freflag = new FreFlagValue();
                                                    pp_param.Freq[k] = freflag.FreDic[frequencys_ConType[ObsSatsDataDicKey[i]][k]];
                                                }
                                                #endregion 频点赋值

                                                pp_input.SysType = ObsSatsDataDicKey[i];
                                                PPositionDLL.PPositioning(pp_input, pp_param, out pp_output, PositionType);
                                                RecFixedData.Add(ObsSatsDataDicKey[i], pp_output);

                                                SatNumFlag = 0;
                                            }

                                            if ((0 == SatNumFlag) & (pp_input.ObsTotalSatnum < 4))
                                            {
                                                MessageBox.Show("可见星少于4颗，不能正确定位！");
                                                DlgReportSimInfo(SimInfo.NewSimInfo(this.Name, "可见星少于4颗，不能正确定位", OutputType.消息, GlobalCurrentTime));
                                                SatNumFlag = 1;
                                            }

                                        }
                                        if ((0 == pp_input.ObsTotalSatnum) & (SatNumFlag != 2))
                                        {
                                            DlgReportSimInfo(SimInfo.NewSimInfo(this.Name, "没有可见卫星，不能正确定位", OutputType.消息, GlobalCurrentTime));
                                            SatNumFlag = 2;
                                        }

                                    }
                                }
                            }
                        }

                        if (0 == MasterStaFlag)
                        {
                            MessageBox.Show("没有星历数据，请添加主控站！");
                            MasterStaFlag = 1;
                        }

                    }
                }
            }

            if (true)//根据判断确定使用哪个系统的定位结果
            {
                if (0 == RecFixedData.Count)//如果可见卫星个数少于4，则定位结果默认为0
                {
                    PPositionning_Output pp_output1 = new PPositionning_Output();
                    pp_output1.X = new double[3];
                    pp_output1.X[0] = 0;
                    pp_output1.X[1] = 0;
                    pp_output1.X[2] = 0;

                    RecFixedData.Add(ObsSatsDataDicKey[0], pp_output1);
                }
                NodePosVel tempp = new NodePosVel();
                tempp.epoch = BDSimObject.GlobalCurrentTime;
                tempp.x = RecFixedData[ObsSatsDataDicKey[0]].X[0];
                tempp.y = RecFixedData[ObsSatsDataDicKey[0]].X[1];
                tempp.z = RecFixedData[ObsSatsDataDicKey[0]].X[2];
                FixedPosVelXYZ = tempp;
                DopResult = RecFixedData[ObsSatsDataDicKey[0]].DOP;
            }
            #region 不考虑多系统
            //GroundSegment temp = new GroundSegment();
            //temp = (Parent.Parent.Parent as Scenario).SegmentColletion[2] as GroundSegment;
            ObservableCollection<StationBase> StationList = new ObservableCollection<StationBase>();


            #endregion 不考虑多系统
        }

        /// <summary>
        /// 实测数据进行接收机定位
        /// </summary>
        /// <param name="SatEph16Dic">当前时刻有效星历数据</param>
        /// <param name="ClockErrDic">当前时刻有效卫星钟差数据</param>
        /// <param name="ObsSatsDataDic">当前时刻接收机观测数据</param>
        /// <param name="IonEightParam">电离层数据</param>
        /// <param name="receiverPosition">接收机概略位置</param>
        public void OriginalDataPVT(Dictionary<string, Ephemeris_16> SatEph16Dic, Dictionary<string, ClkErrFitMsg> ClockErrDic, Dictionary<string, List<ObsReceiverOutput>> ObsSatsDataDic, IonoSphere_8 IonEightParam, double[] receiverPosition)
        {

            PPositionning_Input pp_input = new PPositionning_Input();
            PPositionning_Param pp_param = new PPositionning_Param();
            PPositionning_Output pp_output = new PPositionning_Output();

            if ((0 == SatEph16Dic.Count()) & (0 == EphNumFlag))
            {
                MessageBox.Show("没有星历数据，不能完成定位功能！");
                EphNumFlag = 1;
            }

            if (SatEph16Dic.Count() > 4)
            {
                pp_input.CurTime = ObsSatsDataDic.First().Value.First().CurTime;
                pp_input.ReceiverID = 1;
                pp_input.ReceiverPos = receiverPosition;

                pp_input.ObsTotalSatnum = ObsSatsDataDic.Count();//获取当前星座中可见星个数
                if (pp_input.ObsTotalSatnum > 0)
                {
                    List<string> satNameList = ObsSatsDataDic.Keys.ToList();//获取当前星座中可见星名称

                    //double nowTime = (BDSimObject.GlobalCurrentTime.Jd - BDSimObject.GlobalStartTime.Jd) * 86400.0;//运行时间长度

                    //int NavMsgId = (int)(nowTime / 3600.0);//因1小时生成一组星历，用于判断取第几组星历数据
                    //if (NavMsgId == SatEph16Dic[satNameList[0]].Count())
                    //{
                    //    NavMsgId--;
                    //}

                    pp_input.ObsSatInfo = new SatInfo[20];
                    if (pp_input.ObsTotalSatnum >= 4)
                    {
                        for (int j = 0; j < pp_input.ObsTotalSatnum; j++)
                        {
                            pp_input.ObsSatInfo[j].SatID = ObsSatsDataDic[satNameList[j]][0].SatID;//卫星编号

                            //观测数据赋值
                            pp_input.ObsSatInfo[j].SatObs.SatID = ObsSatsDataDic[satNameList[j]][0].SatID;//卫星编号
                            pp_input.ObsSatInfo[j].SatObs.Code_Pseudo = new double[6];
                            pp_input.ObsSatInfo[j].SatObs.Carrier_Phase = new double[6];

                            for (int k = 0; k < ObsSatsDataDic[satNameList[j]].Count(); k++)//有多少个频点的观测数据赋多少个值
                            {
                                pp_input.ObsSatInfo[j].SatObs.Code_Pseudo[k] = ObsSatsDataDic[satNameList[j]][k].SatObs.A_Pseudo_writein;
                                pp_input.ObsSatInfo[j].SatObs.Carrier_Phase[k] = ObsSatsDataDic[satNameList[j]][k].SatObs.A_Carri_writein;
                            }

                            //星历数据赋值
                            pp_input.ObsSatInfo[j].SingleSatNavMsg.SatID = ObsSatsDataDic[satNameList[j]][0].SatID;//卫星编号
                            //pp_input.ObsSatInfo[j].SingleSatNavMsg.EphemerisSixteen = SatEph16Dic[satNameList[j]][NavMsgId];
                            //pp_input.ObsSatInfo[j].SingleSatNavMsg.ClkErrMsg = ClockErrDic[satNameList[j]][NavMsgId];
                            pp_input.ObsSatInfo[j].SingleSatNavMsg.EphemerisSixteen = SatEph16Dic[satNameList[j]];
                            pp_input.ObsSatInfo[j].SingleSatNavMsg.ClkErrMsg = ClockErrDic[satNameList[j]];
                            pp_input.ObsSatInfo[j].SingleSatNavMsg.IonEightParam = IonEightParam;
                        }

                        #region 误差控制参数赋值
                        pp_param.Iion = 1;
                        switch (IonModelPVT)
                        {
                            case EIonModelType.EightParam:
                                pp_param.m_nMode = 1;
                                break;
                            case EIonModelType.DoubleFre:
                                pp_param.m_nMode = 2;
                                break;
                            case EIonModelType.不考虑:
                                pp_param.Iion = 0;
                                break;
                            default:
                                break;
                        }

                        switch (TroModelPVT)//
                        {
                            case ETroModelType.Hopfield:
                                pp_param.Itro = 1;
                                break;
                            case ETroModelType.ImprovedHopfield:
                                pp_param.Itro = 1;
                                break;
                            case ETroModelType.Saastamoinen:
                                pp_param.Itro = 1;
                                break;
                            case ETroModelType.不考虑:
                                pp_param.Itro = 0;
                                break;
                            default:
                                break;
                        }

                        switch (RelModelPVT)
                        {
                            case ERelModelType.自定义模型:
                                pp_param.Irel = 1;
                                break;
                            case ERelModelType.不考虑:
                                pp_param.Irel = 0;
                                break;
                            default:
                                break;
                        }

                        switch (SatclkModelPVT)
                        {
                            case ESatClkModelType.多项式模型:
                                pp_param.Iclo = 1;
                                break;
                            case ESatClkModelType.不考虑:
                                pp_param.Iclo = 0;
                                break;
                            default:
                                break;
                        }
                        #endregion 误差控制参数赋值

                        #region 频点赋值
                        //Dictionary<EConstellationType, List<double>> frequencys_ConType = new Dictionary<EConstellationType, List<double>>();//分星座存储频点

                        //string[] rectypetemp = RecType.ToString().Split(new string[1] { "_" }, StringSplitOptions.RemoveEmptyEntries);
                        ////判断星座类型，
                        char sign = ObsSatsDataDic.First().Key.First();
                        EConstellationType ConstellationType = sign == 'C' ? EConstellationType.BD : EConstellationType.GPS;

                        //foreach (string recType in rectypetemp)
                        //{
                        //    List<double> frequencys = new List<double>();

                        //    if (recType == ConstellationType.ToString())
                        //    {
                        //        double frequency = 0.0;
                        //        for (int k = 0; k < RecFre.Count(); k++)
                        //        {
                        //            string[] recfreFlag = RecFre[k].ToString().Split(new string[1] { "_" }, StringSplitOptions.RemoveEmptyEntries);
                        //            switch ((RecFre[k]))
                        //            {
                        //                case EFrePoint.BD_B1:
                        //                    if (recfreFlag[0] == recType)
                        //                    {
                        //                        frequency = 1561.098;
                        //                        frequencys.Add(frequency);
                        //                    }
                        //                    break;
                        //                case EFrePoint.BD_B2:
                        //                    if (recfreFlag[0] == recType)
                        //                    {
                        //                        frequency = 1207.14;
                        //                        frequencys.Add(frequency);
                        //                    }
                        //                    break;
                        //                case EFrePoint.BD_B3:
                        //                    if (recfreFlag[0] == recType)
                        //                    {
                        //                        frequency = 1268.52;
                        //                        frequencys.Add(frequency);
                        //                    }
                        //                    break;
                        //                case EFrePoint.GPS_L1:
                        //                    if (recfreFlag[0] == recType)
                        //                    {
                        //                        frequency = 1575.42;
                        //                        frequencys.Add(frequency);
                        //                    }
                        //                    break;
                        //                case EFrePoint.GPS_L2:
                        //                    if (recfreFlag[0] == recType)
                        //                    {
                        //                        frequency = 1227.60;
                        //                        frequencys.Add(frequency);
                        //                    }
                        //                    break;
                        //                case EFrePoint.GPS_L5:
                        //                    if (recfreFlag[0] == recType)
                        //                    {
                        //                        frequency = 1176.45;
                        //                        frequencys.Add(frequency);
                        //                    }
                        //                    break;
                        //                case EFrePoint.GLONASS_L1:
                        //                    if (recfreFlag[0] == recType)
                        //                    {
                        //                        frequency = 1602;
                        //                        frequencys.Add(frequency);
                        //                    }
                        //                    break;
                        //                case EFrePoint.GLONASS_L2:
                        //                    if (recfreFlag[0] == recType)
                        //                    {
                        //                        frequency = 1246;
                        //                        frequencys.Add(frequency);
                        //                    }
                        //                    break;
                        //                case EFrePoint.GALILEO_E1:
                        //                    if (recfreFlag[0] == recType)
                        //                    {
                        //                        frequency = 1575.42;
                        //                        frequencys.Add(frequency);
                        //                    }
                        //                    break;
                        //                case EFrePoint.GALILEO_E5a:
                        //                    if (recfreFlag[0] == recType)
                        //                    {
                        //                        frequency = 1176.45;
                        //                        frequencys.Add(frequency);
                        //                    }
                        //                    break;
                        //            }
                        //        }
                        //        frequencys_ConType.Add(ConstellationType, frequencys);
                        //    }

                        //}
                        //pp_param.Freq = new double[3];
                        //for (int k = 0; k < frequencys_ConType[ConstellationType].Count(); k++)//定位时输入的接收机频率不大于3
                        //{
                        //    pp_param.Freq[k] = frequencys_ConType[ConstellationType][k];
                        //}
                        #endregion 频点赋值
                        switch (ConstellationType)
                        {
                            case EConstellationType.BD:
                                pp_param.Freq = new double[3] { 1561.098, 0, 0 };
                                break;
                            case EConstellationType.GPS:
                                pp_param.Freq = new double[3] { 1575.42, 0, 0 };
                                break;
                            case EConstellationType.GLONASS:
                                break;
                            case EConstellationType.GALILEO:
                                break;
                            default:
                                break;
                        }

                        PPositionDLL.PPositioning(pp_input, pp_param, out pp_output, PositionType);
                        //RecFixedData.Add(ConstellationType, pp_output);
                        NodePosVel fixPosition = new NodePosVel();
                        fixPosition.epoch = ObsSatsDataDic.First().Value.First().CurTime;
                        fixPosition.x = pp_output.X[0];
                        fixPosition.y = pp_output.X[1];
                        fixPosition.z = pp_output.X[2];
                        //FixedPosVelXYZ = tempp;
                        //DopResult = pp_output.DOP;
                        SatNumFlag = 0;

                        UpdateResult(ObsSatsDataDic.First().Value.First().CurTime, fixPosition, receiverPosition, pp_output.DOP);
                    }

                    if ((0 == SatNumFlag) & (pp_input.ObsTotalSatnum < 4))
                    {
                        //MessageBox.Show("可见星少于4颗，不能正确定位！");
                        DlgReportSimInfo(SimInfo.NewSimInfo(this.Name, "可见星少于4颗，不能正确定位", OutputType.消息, GlobalCurrentTime));
                        SatNumFlag = 1;
                    }

                }
                if ((0 == pp_input.ObsTotalSatnum) & (SatNumFlag != 2))
                {
                    DlgReportSimInfo(SimInfo.NewSimInfo(this.Name, "没有可见卫星，不能正确定位", OutputType.消息, GlobalCurrentTime));
                    SatNumFlag = 2;
                }
            }
        }

        void UpdateResult(UTCTime time, NodePosVel fixPosition, double[] receiverPosition, DopDLL.DopOutput dopResult)
        {
            NodePosVel ppositionError = new NodePosVel() { epoch = time, x = fixPosition.X - receiverPosition[0], y = fixPosition.Y - receiverPosition[1], z = fixPosition.Z - receiverPosition[2] };
            if (_UpDatePPositionResult != null)
            {
                _UpDatePPositionResult(ppositionError, fixPosition, time, SatSpaceParamList, dopResult);
            }
        }
        #endregion 单步运行中的函数

        #region 计算星空参数方法
        /// <summary>
        /// 计算星空参数方法
        /// </summary>
        public void CalculateSatSpaceParam()
        {
            SatSpaceParamList.Clear();
            foreach (var satellite in (Parent.Parent.Parent.SegmentColletion[0] as SpaceSegment).AllSatellite)
            {
                double Ele = 0; //高度角
                double Azi = 0; //方位角
                //  double[] satPos = new double[3] { satellite.Orbit.RealECFPV.X, satellite.Orbit.RealECFPV.Y, satellite.Orbit.RealECFPV.Z };
                //  double[] userPos = new double[3] { Parent.PosVelXYZ.X, Parent.PosVelXYZ.Y, Parent.PosVelXYZ.Z };
                SatPredictStatus tempSatStatus = new SatPredictStatus();///新建对象后，可见性Visible默认为false
                tempSatStatus.SatType = satellite.Parent.ConstellationFeature.ConstellationType;
                tempSatStatus.PRN = satellite.Id;
                tempSatStatus.satName = satellite.Name;
                tempSatStatus.Visible = true;
                //CalEleAziDLL.Cal_EleAzi(userPos, satPos, ref Ele, ref Azi);
                int Access = CAccessCalDLL.StationAccess(Parent.PosVelXYZ, satellite.Orbit.RealECFPV, ECFtype.type_CGCS2000, Elelim, out Ele, out Azi);
                tempSatStatus.PosX = satellite.Orbit.RealECFPV.X;
                tempSatStatus.PosY = satellite.Orbit.RealECFPV.Y;
                tempSatStatus.PosZ = satellite.Orbit.RealECFPV.Z;
                tempSatStatus.Elevation = Ele;
                tempSatStatus.Azimuth = Azi;

                if (Access != 1)
                {
                    tempSatStatus.Visible = false;
                }
                else
                {
                    //tempSatStatus.PseudoRange = ObsSatsDataDic[satellite.Name][0].SatObs.A_Pseudo_writein;//显示第一个频点的伪距观测数据值
                    //tempSatStatus.Phase = ObsSatsDataDic[satellite.Name][0].SatObs.A_Carri_writein;//显示第一个频点的载波相位观测数据值

                    tempSatStatus.PseudoRange = ObsSatsDataDic_ConType[satellite.Parent.ConstellationFeature.ConstellationType][satellite.Name][0].SatObs.A_Pseudo_writein; ;//显示第一个频点的伪距观测数据值
                    tempSatStatus.Phase = ObsSatsDataDic_ConType[satellite.Parent.ConstellationFeature.ConstellationType][satellite.Name][0].SatObs.A_Carri_writein;//显示第一个频点的载波相位观测数据值
                }
                SatSpaceParamList.Add(tempSatStatus);
            }
        }
        #endregion

        public override string ToString()
        {
            if (Parent != null)
            {
                return Parent.Name + "<" + this.Name + ">";
            }
            else
            {
                return this.Name;
            }
        }

        #region 实现定位评估的接口
        [XmlIgnore, Browsable(false)]
        public Action<NodePosVel, NodePosVel, UTCTime, List<SatPredictStatus>, DopDLL.DopOutput> UpDatePPositionResult
        {
            get
            {
                return _UpDatePPositionResult;
            }
            set
            {
                _UpDatePPositionResult = value;
            }
        }
        #endregion
    }
}
